Ext.ns('Ext.ux');
/**
 * Plugin for adding a tab menu to a TabBar is the Tabs overflow.
 */
Ext.define('Ext.ux.TabScrollerMenu', {
	alias : 'plugin.tabscrollermenu',

	requires : ['Ext.menu.Menu'],

	/**
	 * @cfg {Number} pageSize How many items to allow per submenu.
	 */
	pageSize : 10,
	/**
	 * @cfg {Number} maxText How long should the title of each
	 *      {@link Ext.menu.Item} be.
	 */
	maxText : 15,
	/**
	 * @cfg {String} menuPrefixText Text to prefix the submenus.
	 */
	menuPrefixText : 'Items',

	/**
	 * Creates new TabScrollerMenu.
	 * 
	 * @param {Object}
	 *            config Configuration options
	 */
	constructor : function(config) {
		Ext.apply(this, config);
	},

	// private
	init : function(tabPanel) {
		var me = this;

		me.tabPanel = tabPanel;

		tabPanel.on({
					render : function() {
						me.tabBar = tabPanel.tabBar;
						me.layout = me.tabBar.layout;
						me.layout.overflowHandler.handleOverflow = Ext.Function
								.bind(me.showButton, me);
						me.layout.overflowHandler.clearOverflow = Ext.Function
								.createSequence(
										me.layout.overflowHandler.clearOverflow,
										me.hideButton, me);
					},
					destroy : me.destroy,
					scope : me,
					single : true
				});
	},

	showButton : function() {
		var me = this, result = Ext.getClass(me.layout.overflowHandler).prototype.handleOverflow
				.apply(me.layout.overflowHandler, arguments), button = me.menuButton;

		if (me.tabPanel.items.getCount() > 1) {
			if (!button) {
				button = me.menuButton = me.tabBar.body.createChild({
							cls : Ext.baseCSSPrefix + 'tab-tabmenu-right'
						}, me.tabBar.body.child('.' + Ext.baseCSSPrefix
								+ 'box-scroller-right'));
				button.addClsOnOver(Ext.baseCSSPrefix + 'tab-tabmenu-over');
				button.on('click', me.showTabsMenu, me);
			}
			button.setVisibilityMode(Ext.dom.Element.DISPLAY);
			button.show();
			result.reservedSpace += button.getWidth();
		} else {
			me.hideButton();
		}
		return result;
	},

	hideButton : function() {
		var me = this;
		if (me.menuButton) {
			me.menuButton.hide();
		}
	},

	/**
	 * Returns an the current page size (this.pageSize);
	 * 
	 * @return {Number} this.pageSize The current page size.
	 */
	getPageSize : function() {
		return this.pageSize;
	},
	/**
	 * Sets the number of menu items per submenu "page size".
	 * 
	 * @param {Number}
	 *            pageSize The page size
	 */
	setPageSize : function(pageSize) {
		this.pageSize = pageSize;
	},
	/**
	 * Returns the current maxText length;
	 * 
	 * @return {Number} this.maxText The current max text length.
	 */
	getMaxText : function() {
		return this.maxText;
	},
	/**
	 * Sets the maximum text size for each menu item.
	 * 
	 * @param {Number}
	 *            t The max text per each menu item.
	 */
	setMaxText : function(t) {
		this.maxText = t;
	},
	/**
	 * Returns the current menu prefix text String.;
	 * 
	 * @return {String} this.menuPrefixText The current menu prefix text.
	 */
	getMenuPrefixText : function() {
		return this.menuPrefixText;
	},
	/**
	 * Sets the menu prefix text String.
	 * 
	 * @param {String}
	 *            t The menu prefix text.
	 */
	setMenuPrefixText : function(t) {
		this.menuPrefixText = t;
	},

	showTabsMenu : function(e) {
		var me = this;

		if (me.tabsMenu) {
			me.tabsMenu.removeAll();
		} else {
			me.tabsMenu = new Ext.menu.Menu();
		}

		me.generateTabMenuItems();

		var target = Ext.get(e.getTarget()), xy = target.getXY();

		// Y param + 24 pixels
		xy[1] += 24;

		me.tabsMenu.showAt(xy);
	},

	// private
	generateTabMenuItems : function() {
		var me = this, tabPanel = me.tabPanel, curActive = tabPanel
				.getActiveTab(), allItems = tabPanel.items.getRange(), pageSize = me
				.getPageSize(), tabsMenu = me.tabsMenu, totalItems, numSubMenus, remainder, i, curPage, menuItems, x, item, start, index;

		tabsMenu.suspendLayouts();
		allItems = Ext.Array.filter(allItems, function(item) {
					if (item.id == curActive.id) {
						return false;
					}
					return item.hidden ? !!item.hiddenByLayout : true;
				});
		totalItems = allItems.length;
		numSubMenus = Math.floor(totalItems / pageSize);
		remainder = totalItems % pageSize;

		if (totalItems > pageSize) {

			// Loop through all of the items and create submenus in chunks of 10
			for (i = 0; i < numSubMenus; i++) {
				curPage = (i + 1) * pageSize;
				menuItems = [];

				for (x = 0; x < pageSize; x++) {
					index = x + curPage - pageSize;
					item = allItems[index];
					menuItems.push(me.autoGenMenuItem(item));
				}

				tabsMenu.add({
							text : me.getMenuPrefixText() + ' '
									+ (curPage - pageSize + 1) + ' - '
									+ curPage,
							menu : menuItems
						});
			}
			// remaining items
			if (remainder > 0) {
				start = numSubMenus * pageSize;
				menuItems = [];
				for (i = start; i < totalItems; i++) {
					item = allItems[i];
					menuItems.push(me.autoGenMenuItem(item));
				}

				me.tabsMenu.add({
							text : me.menuPrefixText + ' ' + (start + 1)
									+ ' - ' + (start + menuItems.length),
							menu : menuItems
						});

			}
		} else {
			for (i = 0; i < totalItems; ++i) {
				tabsMenu.add(me.autoGenMenuItem(allItems[i]));
			}
		}
		tabsMenu.resumeLayouts(true);
	},

	// private
	autoGenMenuItem : function(item) {
		var maxText = this.getMaxText(), text = Ext.util.Format.ellipsis(
				item.title, maxText);

		return {
			text : text,
			handler : this.showTabFromMenu,
			scope : this,
			disabled : item.disabled,
			tabToShow : item,
			iconCls : item.iconCls
		};
	},

	// private
	showTabFromMenu : function(menuItem) {
		this.tabPanel.setActiveTab(menuItem.tabToShow);
	},

	destroy : function() {
		Ext.destroy(this.tabsMenu, this.menuButton);
	}
});
